using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Xml.Serialization;
using EnvDTE;
using Microsoft.VisualStudio.Shell.Interop;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Windows;
using System.Windows.Input;
using System.Threading;
using System.Windows.Threading;
using System.Net;
using System.Threading.Tasks;

namespace WebAppUploader
{
	public class ProjectModel : INotifyPropertyChanged
	{
		public ProjectModel()
		{
			_ConfigCommand = new ActionCommand<object>(x => OnConfigCommand());
			_AddProfileCommand =new ActionCommand<object>(x=> Profiles.Add(new ProjectProfileModel{ Name="Undefined" }) );
			_DeleteProfileCommand = new ActionCommand<ProjectProfileModel>(x => OnDeleteProfile(x));
		}

		#region private object OnDeleteProfile(ProjectProfileModel x)
		private void OnDeleteProfile(ProjectProfileModel x)
		{
			if (MessageBox.Show("Are you sure you want to delete?", "Delete", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes)
				return;
			Profiles.Remove(x);
		}
		#endregion


		#region private object OnConfigCommand()
		private void OnConfigCommand()
		{
			ProfileListDialog dlg = new ProfileListDialog();
			dlg.DataContext = this;
			dlg.ShowDialog();

			// select first...
			if (_SelectedProfile == null) {
				_SelectedProfile = Profiles.FirstOrDefault();
				if (_SelectedProfile != null) {
					CurrentProfile = _SelectedProfile.Name;
				}
			}

			foreach (var item in Profiles)
			{
				item.project = project;
				item.RefreshCommand.Execute(this);
			}
		}
		#endregion


		public static Dictionary<string, ProjectModel> Cache = new Dictionary<string, ProjectModel>();

		public static ProjectModel Open(string path, Project p)
		{
			ProjectModel model = null;
			lock (Cache)
			{
				if (Cache.TryGetValue(path, out model))
					return model;
				model = LoadFrom(path);
				Cache[path] = model;
			}
			model.project = p;
			model.RefreshFiles();

			return model;
		}

		#region private void RefreshFiles()
		private void RefreshFiles()
		{
			foreach (var item in Profiles)
			{
				item.project = this.project;
				item.RefreshCommand.Execute(this);
			}
		}
		#endregion


		public static ProjectModel LoadFrom(String path) {
			DirectoryInfo localPath = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\WebUploader\\");
			if (!localPath.Exists)
				localPath.Create();

			FileInfo projectIndex = new FileInfo(localPath.FullName + GetProjectName(path) + ".xml");
			try
			{
				if (!projectIndex.Exists)
				{
					return new ProjectModel { ProjectPath = path, ConfigPath=projectIndex.FullName };
				}

				XmlSerializer xs = new XmlSerializer(typeof(ProjectModel));
				ProjectModel model;
				using (FileStream fs = projectIndex.OpenRead())
				{
					model = (ProjectModel)xs.Deserialize(fs);
				}
				return model;
			}
			catch (Exception ex) {
				MessageBox.Show(ex.ToString());
				return new ProjectModel { ProjectPath = path, ConfigPath = projectIndex.FullName };
			}
		}

		#region private static string GetProjectName(string path)
		private static string GetProjectName(string path)
		{
			MD5 m = MD5.Create();
			byte[] data = System.Text.Encoding.Default.GetBytes(path);
			data = m.ComputeHash(data);
			return data.ToBase32String();
		}
		#endregion

		public void Save() {
			XmlSerializer xs = new XmlSerializer(this.GetType());
			if (File.Exists(ConfigPath))
				File.Delete(ConfigPath);
			using (FileStream fs = File.OpenWrite(ConfigPath))
			{
				xs.Serialize(fs,this);
			}
		}

		#region Property ConfigCommand
		private ICommand _ConfigCommand = null;
		[XmlIgnore]
		public ICommand ConfigCommand
		{
			get
			{
				return _ConfigCommand;
			}
		}

		#endregion

		#region Property AddProfileCommand
		private ICommand _AddProfileCommand = null;
		public ICommand AddProfileCommand
		{
			get
			{
				return _AddProfileCommand;
			}
		}

		#endregion

		#region Property DeleteProfileCommand
		private ICommand _DeleteProfileCommand = null;
		public ICommand DeleteProfileCommand
		{
			get
			{
				return _DeleteProfileCommand;
			}
		}

		#endregion
	

		private Project project;


		#region Property ProjectPath
		private string _ProjectPath = "";
		[System.ComponentModel.Bindable(true)]
		[System.ComponentModel.DefaultValue("")]
		[System.ComponentModel.Category("Category")]
		public string ProjectPath
		{
			get
			{
				return _ProjectPath;
			}
			set
			{
				_ProjectPath = value;
				if (PropertyChanged != null)
					PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("ProjectPath"));
			}
		}

		#endregion

		#region Property ConfigPath
		private string _ConfigPath = "";
		[System.ComponentModel.Bindable(true)]
		[System.ComponentModel.DefaultValue("")]
		[System.ComponentModel.Category("Category")]
		public string ConfigPath
		{
			get
			{
				return _ConfigPath;
			}
			set
			{
				_ConfigPath = value;
				if (PropertyChanged != null)
					PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("ConfigPath"));
			}
		}

		#endregion

		public event PropertyChangedEventHandler PropertyChanged;

		public ProjectProfileModel[] ProfileArray
		{
			get
			{
				return _Profiles.ToArray();
			}
			set
			{
				_Profiles.Clear();
				foreach (var item in value)
				{
					_Profiles.Add(item);
				}
			}
		}

		#region Property Profiles
		private ObservableCollection<ProjectProfileModel> _Profiles = new ObservableCollection<ProjectProfileModel>();
		[XmlIgnore]
		public ObservableCollection<ProjectProfileModel> Profiles
		{
			get
			{
				return _Profiles;
			}
		}
		#endregion

		#region Property CurrentProfile
		private string _CurrentProfile = null;
		[System.ComponentModel.Bindable(true)]
		[System.ComponentModel.DefaultValue("")]
		[System.ComponentModel.Category("Category")]
		public string CurrentProfile
		{
			get
			{
				return _CurrentProfile;
			}
			set
			{
				_CurrentProfile = value;
				_SelectedProfile = Profiles.FirstOrDefault(x => x.Name == _CurrentProfile);
				if (PropertyChanged != null)
				{
					PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("CurrentProfile"));
					PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("SelectedProfile"));
				}
			}
		}

		#endregion

		#region Property SelectedProfile
		private ProjectProfileModel _SelectedProfile = null;
		public ProjectProfileModel SelectedProfile
		{
			get
			{
				return _SelectedProfile;
			}
		}
		#endregion
	
	}
}